home *** CD-ROM | disk | FTP | other *** search
- /*
- File: BaseStation.c
-
- Contains: Class to handle a base station
-
- Version: MacHack 2001
- */
-
- #include "BaseStation.h"
-
- #include <stdio.h>
- #include <math.h>
-
- struct BaseLocation
- {
- UInt16 fMACAddress[3];
- UInt32 fX;
- UInt32 fY;
- const char* fName;
- };
-
-
- BaseLocation sBaseLocations[] = {
- { 0x0060, 0x1D1E, 0x3703, 357, 211, "Balcony"},
- { 0x0060, 0x1D1E, 0xE6AE, 376, 91, "Machine Room"},
- { 0x0060, 0x1DF6, 0x8C27, 47, 623, "Sicily"},
- { 0x0060, 0x1DF0, 0x0E49, 395, 661, "Hotel Desk"},
- { 0x0060, 0x1D1E, 0x324E, 672, 97, "C&G Far"},
- { 0x0060, 0x1DF0, 0x0B26, 555, 26, "C&G Middle"}
- };
-
- // ---------------------------------------------------------------------------
- // BaseStation
- // ---------------------------------------------------------------------------
-
- BaseStation::BaseStation()
- {
- fSignal = 0.0;
- fSignalAverage = 0.0;
- fNoise = 0.0;
-
- fMACAddress[0] = 0;
- fMACAddress[1] = 0;
- fMACAddress[2] = 0;
-
- fX = 0.0;
- fY = 0.0;
-
- fR = 0.0;
-
- fName = "";
- }
-
- // ---------------------------------------------------------------------------
- // ~BaseStation
- // ---------------------------------------------------------------------------
-
- BaseStation::~BaseStation()
- {
- }
-
- // ---------------------------------------------------------------------------
- // UpdateInfo
- // ---------------------------------------------------------------------------
-
- void BaseStation::UpdateInfo(WirelessNodeInfoPtr inBaseInfo)
- {
- fSignal = inBaseInfo->fSignalLevel;
- fSignalAverage = (fSignalAverage + fSignal) / 2.0;
- fNoise = inBaseInfo->fNoiseLevel;
-
- fMACAddress[0] = inBaseInfo->fMACAddress[0];
- fMACAddress[1] = inBaseInfo->fMACAddress[1];
- fMACAddress[2] = inBaseInfo->fMACAddress[2];
- }
-
-
- // ---------------------------------------------------------------------------
- // BaseStationList
- // ---------------------------------------------------------------------------
-
- BaseStationList::BaseStationList()
- {
- OSStatus error = noErr;
-
- fBaseCount = 0;
- fRef = 0;
-
- fX = 0.0;
- fY = 0.0;
-
- error = WirelessConnect(&fRef, 0);
- }
-
- // ---------------------------------------------------------------------------
- // ~BaseStationList
- // ---------------------------------------------------------------------------
-
- BaseStationList::~BaseStationList()
- {
- if (fRef)
- {
- WirelessDisconnect(fRef);
- }
- }
-
-
- // ---------------------------------------------------------------------------
- // CalcDistanceSquared
- // ---------------------------------------------------------------------------
-
- double
- BaseStationList::CalcDistanceSquared(
- const SectPoint & inPoint1,
- const SectPoint & inPoint2)
- {
- double xDiff = inPoint1.fX - inPoint2.fX;
- double yDiff = inPoint1.fY - inPoint2.fY;
- return xDiff * xDiff + yDiff * yDiff;
- }
-
-
- // ---------------------------------------------------------------------------
- // FindMostLikelyLocation
- // ---------------------------------------------------------------------------
-
- void
- BaseStationList::FindMostLikelyLocation(
- const SectPoints * inSectPoint,
- UInt32 inSectPointCount)
- {
- // Among each of the intersection pairs, one of the
- // points is correct. We can guess which one is correct
- // by triangulation (i.e. comparing the points to find
- // "similar" points).
-
- double totalDiff1 = 0.0;
- double totalDiff2 = 0.0;
- SectPoint xyTotal1 = inSectPoint[0].fPoint1;
- SectPoint xyTotal2 = inSectPoint[0].fPoint2;
-
- for (UInt32 i = 1; i < inSectPointCount; i++)
- {
- double diff1;
- double diff2;
-
- diff1 = CalcDistanceSquared(inSectPoint[0].fPoint1, inSectPoint[i].fPoint1);
- diff2 = CalcDistanceSquared(inSectPoint[0].fPoint1, inSectPoint[i].fPoint2);
-
- // Is point1[0] closer to point1[i] or point2[i]?
- if (diff1 < diff2)
- {
- totalDiff1 += diff1;
- xyTotal1.fX += inSectPoint[i].fPoint1.fX;
- xyTotal1.fY += inSectPoint[i].fPoint1.fY;
- }
- else
- {
- totalDiff1 += diff2;
- xyTotal1.fX += inSectPoint[i].fPoint2.fX;
- xyTotal1.fY += inSectPoint[i].fPoint2.fY;
- }
-
- diff1 = CalcDistanceSquared(inSectPoint[0].fPoint2, inSectPoint[i].fPoint1);
- diff2 = CalcDistanceSquared(inSectPoint[0].fPoint2, inSectPoint[i].fPoint2);
-
- // Is point2[0] closer to point1[i] or point2[i]?
- if (diff1 < diff2)
- {
- totalDiff1 += diff1;
- xyTotal2.fX += inSectPoint[i].fPoint1.fX;
- xyTotal2.fY += inSectPoint[i].fPoint1.fY;
- }
- else
- {
- totalDiff1 += diff2;
- xyTotal2.fX += inSectPoint[i].fPoint2.fX;
- xyTotal2.fY += inSectPoint[i].fPoint2.fY;
- }
- }
-
- if (totalDiff1 < totalDiff2)
- {
- fX = xyTotal1.fX / inSectPointCount;
- fY = xyTotal1.fY / inSectPointCount;
- }
- else
- {
- fX = xyTotal2.fX / inSectPointCount;
- fY = xyTotal2.fY / inSectPointCount;
- }
- }
-
-
- // ---------------------------------------------------------------------------
- // FindIntersectionPoints
- // ---------------------------------------------------------------------------
-
- void
- BaseStationList::FindIntersectionPoints(
- BaseStation * inBase1,
- BaseStation * inBase2,
- SectPoints & outSectPoint)
- {
- double xDiff = inBase2->fX - inBase1->fX;
- double yDiff = inBase2->fY - inBase1->fY;
- double distance = sqrt(xDiff * xDiff + yDiff * yDiff);
-
- outSectPoint.fBaseStation1 = inBase1;
- outSectPoint.fBaseStation2 = inBase2;
-
- double scaleFactor = inBase1->fR / (inBase1->fR + inBase2->fR);
- SectPoint scaledCenter;
- scaledCenter.fX = inBase1->fX + xDiff * scaleFactor;
- scaledCenter.fY = inBase1->fY + yDiff * scaleFactor;
-
- // If the two don't intersect, we have to assume that
- // the location is between the two.
- if (distance >= inBase1->fR + inBase2->fR)
- {
- outSectPoint.fPoint1 = scaledCenter;
- outSectPoint.fPoint2 = scaledCenter;
- }
- else
- {
- // Calculate the distance from the middle of circle one
- // to the center of the chord.
- double chordX = inBase1->fX - scaledCenter.fX;
- double chordY = inBase1->fY - scaledCenter.fY;
- double distanceToChordSq = chordX * chordX + chordY * chordY;
-
- // Calculate how far along the chord in each direction we
- // need to travel to get to the circle.
- double distanceAlongChordSq = inBase1->fR * inBase1->fR - distanceToChordSq;
-
- // Determine the slope of the chord (which is the inverse of the
- // slope of the line from the center of the circle to the chord).
- double slopeOfChord = chordX / chordY;
-
- // Solve the following equations:
- // x^2 + y^2 = d^2 d = distance along chord
- // y / x = m m = slope
- // y = xm
- // x^2 + x^2m^2 = d^2
- // x = sqrt(d^2 / (1 + m^2))
- double chordXDiff = sqrt(distanceAlongChordSq / (1 + slopeOfChord * slopeOfChord));
-
- outSectPoint.fPoint1.fX = scaledCenter.fX + chordXDiff;
- outSectPoint.fPoint2.fX = scaledCenter.fX - chordXDiff;
- outSectPoint.fPoint1.fY = scaledCenter.fY - chordXDiff * slopeOfChord;
- outSectPoint.fPoint2.fY = scaledCenter.fY + chordXDiff * slopeOfChord;
- }
- }
-
-
- // ---------------------------------------------------------------------------
- // AddBase
- // ---------------------------------------------------------------------------
-
- void BaseStationList::AddBase(WirelessNodeInfoPtr inBaseInfo)
- {
- UInt32 index;
- Boolean found = false;
-
- for (index = 0; index < fBaseCount; index++)
- {
- if ((fBases[index].fMACAddress[0] == inBaseInfo->fMACAddress[0]) &&
- (fBases[index].fMACAddress[1] == inBaseInfo->fMACAddress[1]) &&
- (fBases[index].fMACAddress[2] == inBaseInfo->fMACAddress[2]))
- {
- found = true;
- break;
- }
- }
-
- if (found == false)
- {
- index = fBaseCount;
- fBaseCount++;
-
- fBases[index].UpdateInfo(inBaseInfo);
-
- for (UInt32 locIndex = 0; locIndex < (sizeof(sBaseLocations)/sizeof(BaseLocation)); locIndex++)
- {
- if ((fBases[index].fMACAddress[0] == sBaseLocations[locIndex].fMACAddress[0]) &&
- (fBases[index].fMACAddress[1] == sBaseLocations[locIndex].fMACAddress[1]) &&
- (fBases[index].fMACAddress[2] == sBaseLocations[locIndex].fMACAddress[2]))
- {
- fBases[index].fX = sBaseLocations[locIndex].fX;
- fBases[index].fY = sBaseLocations[locIndex].fY;
-
- fBases[index].fName = sBaseLocations[locIndex].fName;
-
- found = true;
- break;
- }
- }
- }
- else
- {
- fBases[index].UpdateInfo(inBaseInfo);
- }
- }
-
-
- // ---------------------------------------------------------------------------
- // IdleBases
- // ---------------------------------------------------------------------------
-
- void BaseStationList::IdleBases(void)
- {
- OSStatus error = noErr;
- WirelessNodeInfo nodes[256];
- SInt32 nodeCount;
-
- nodeCount = 256;
-
- error = WirelessScanMerge(fRef, nodes, &nodeCount, 2, 1);
-
- while(nodeCount--)
- {
- AddBase(&(nodes[nodeCount]));
- }
-
- MapMyLocation();
- }
-
-
- // ---------------------------------------------------------------------------
- // MapMyLocation
- // ---------------------------------------------------------------------------
-
- void BaseStationList::MapMyLocation(void)
- {
- // r = -19.73(s) + 1918.5
- UInt32 index;
- UInt32 triIndex;
- BaseStation * baseTriangle[3];
-
- // Scale the values
- for (index = 0; index < fBaseCount; index++)
- {
- fBases[index].fStrongSignal = false;
-
- // Made this shit up
- fBases[index].fR = (-19.73 * fBases[index].fSignalAverage) + 1918.5;
-
- fBases[index].fR = fBases[index].fR / 2.0; // 3.5;
-
- if (fBases[index].fR < 0.01)
- fBases[index].fR = 0.01;
- }
-
- baseTriangle[0] = nil;
- baseTriangle[1] = nil;
- baseTriangle[2] = nil;
-
- // We can't triangulate unless we can see at least two base stations.
- if (fBaseCount > 2)
- {
- // Find the three base stations that have the strongest signals.
- // Lame sort
- for (index = 0; index < fBaseCount; index++)
- {
- for (triIndex = 0; triIndex < 3; triIndex++)
- {
- if (baseTriangle[triIndex])
- {
- if (baseTriangle[triIndex]->fSignalAverage < fBases[index].fSignalAverage)
- {
- for (UInt32 shiftIndex = 2; shiftIndex > triIndex; shiftIndex--)
- {
- baseTriangle[shiftIndex] = baseTriangle[shiftIndex-1];
- }
-
- baseTriangle[triIndex] = &fBases[index];
- break;
- }
- }
- else
- {
- baseTriangle[triIndex] = &fBases[index];
- break;
- }
- }
- }
-
- baseTriangle[0]->fStrongSignal = true;
- baseTriangle[1]->fStrongSignal = true;
- baseTriangle[2]->fStrongSignal = true;
-
- // Find the six points that represent the intersection
- // points of the two circles.
- FindIntersectionPoints(baseTriangle[0], baseTriangle[1], fSectPoints[0]);
- FindIntersectionPoints(baseTriangle[1], baseTriangle[2], fSectPoints[1]);
- FindIntersectionPoints(baseTriangle[0], baseTriangle[2], fSectPoints[2]);
-
- FindMostLikelyLocation(fSectPoints, 3);
- }
- else
- {
- // fix me - handle just two base stations?
- }
- }
-
-